package top.kikt.book.util

import okhttp3.HttpUrl.Companion.toHttpUrl
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.nodes.TextNode
import org.jsoup.select.Elements
import top.kikt.book.core.entity.ChapterMetaEntity

fun Document.selectText(cssQuery: String, trim: Boolean = true): String {
    return select(cssQuery).text().let {
        if (trim) {
            it.trim()
        } else {
            it
        }
    }
}

fun Document.metaContentWithProperty(property: String): String {
    val metas = select("head > meta")
    return metas.firstOrNull {
        it.attr("property") == property
    }?.let {
        return it.attr("content")
    } ?: ""
}

fun Document.getImageUrl(baseUrl: String, cssQuery: String): String {
    val src =
        select(cssQuery).attr("src")
    return baseUrl.toHttpUrl().resolve(src)?.toString() ?: throw IllegalStateException("The ")
}

fun Document.wholeText(cssQuery: String): String {
    val element = select(cssQuery)
    return element[0].wholeText()
}

fun String.resolve(url: String): String {
    return toHttpUrl().resolve(url)?.toString() ?: throw IllegalStateException("Cannot resolve $url of $this")
}

fun String.resolveBySrcUrl(url: String): String {
    return url.resolve(this)
}

fun String.urlEncode(): String {
    val encode = java.net.URLEncoder.encode(this, "utf-8")
    return encode.replace("+", "%20")
}

fun Element.getUrl(srcUrl: String): String {
    val value = attr("href")
    return srcUrl.toHttpUrl().resolve(value)?.toString()
        ?: throw IllegalStateException("Cannot resolve $value of $srcUrl")
}

fun Document.toChapterMetaList(
    cssQuery: String,
    menuUrl: String,
    action: (index: Int, menu: Element) -> ChapterMetaEntity = { index, menu ->
        val title = menu.text()
        val url = menu.attr("href")
        val absUrl = menuUrl.toHttpUrl().resolve(url).toString()
        ChapterMetaEntity(title, index, absUrl, menu)
    }
): List<ChapterMetaEntity> {
    return select(cssQuery).mapIndexed(action)
}


const val prefix = "　　"

fun Element.bookText(indent: String = prefix): String {
    return textNodes().bookText(indent)
}

fun Elements.bookText(indent: String = prefix): String {
    return textNodes().bookText(indent)
}

fun List<TextNode>.bookText(indent: String = prefix): String = filter {
    it.text().trim().isNotEmpty()
}.map {
    it.text()
}.filter {
    it.trim().isNotEmpty()
}.joinToString("\n") {
    it.addIndent(indent)
}

fun String.addIndent(indent: String = prefix): String {
    return "$indent$this"
}
